package cn.tedu.spring6.service;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;




@Component
@Aspect //切面类是需要使用@Aspect注解进行标注的。
@Order(1)
public class LogAspect {//切面
    //切面=通知+切点
    //通知就是增强，就是具体的要编写的增强代码
    //这里通知Advice以方法的形式出现。（因为方法中可以写代码）
    //增强
    //@Before("execution(修饰符 返回值类型 全限定类名 方法名 (形式参数列表) 异常)")
    //@Before("execution(* cn.tedu.spring6.service.UserService.*(..))")
    /*@Before("execution(* cn.tedu.spring6.service..*(..))")
    public void enhance(){
        System.out.println("我是一段通知，是一段增强代码");
    }*/
    //定义通用的切点表达式
    @Pointcut("execution(* cn.tedu.spring6.service..*(..))")
    public void universalCuttingPoint(){
        //这个方法只是一个标记，方法名随意，方法体中也不需要写任何代码
        System.out.println("我这是通用切点");
    }

    //前置通知
    //@Before("execution(* cn.tedu.spring6.service..*(..))")
    @Before("universalCuttingPoint()")
    //public void beforeAdvice(){
    public void beforeAdvice(JoinPoint joinPoint){
        System.out.println("我是一段前置通知...");
        // 这个JoinPoint joinPoint，在Spring容器调用这个方法的时候自动传过来.
        // 我们可以直接用。用这个JoinPoint joinPoint干啥？
        // Signature signature = joinPoint.getSignature(); 获取目标方法的签名。
        // 通过方法的签名可以获取到一个方法的具体信息。
        // 获取目标方法的方法名。
        System.out.println("目标方法的方法名："+joinPoint.getSignature().getName());

    }
    //后置通知
    //@AfterReturning("execution(* cn.tedu.spring6.service..*(..))")
    @AfterReturning("universalCuttingPoint()")
    //public void afterReturningAdvice(){
    public void afterReturningAdvice(JoinPoint joinPoint){
        System.out.println("我是一段后置通知...");
    }
    //环绕通知
    // 环绕通知(环绕是最大的通知，在前置通知之前，在后置通知之后。)
    //@Around("execution(* cn.tedu.spring6.service..*(..))")
    @Around("universalCuttingPoint()")
    public void aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {  //ProceedingJoinPoint joinPoint为连接点
        //前面的代码
        System.out.println("前环绕");
        //执行目标方法
        joinPoint.proceed();
        //后面的代码
        System.out.println("后环绕");
    }
    //异常通知
    //@AfterThrowing("execution(* cn.tedu.spring6.service..*(..))")
    @AfterThrowing("universalCuttingPoint()")
    public void afterThrowingAdvice(){
        System.out.println("异常通知");
    }
    //最终通知
    //@After("execution(* cn.tedu.spring6.service..*(..))")
    @After("universalCuttingPoint()")
public void afterFinallyAdvice(){
    System.out.println("最终通知");
}
}
